/*
*  This program is free software: you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation, either version 3 of the License, or
*  (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#define PLUGIN_NAME		"Reward"
#define PLUGIN_AUTHOR		"Blaize"
#define PLUGIN_DESC		"Give a reward to survivors"
#define PLUGIN_VERSION		"0.1"
#define PLUGIN_FILENAME		"l4d2_reward"
#define TEAM_SPECTATORS		1
#define TEAM_SURVIVORS		2
#define TEAM_INFECTED		3

#define SOUND_REWARD	"ui/pickup_misc42.wav"

#include <sourcemod>
#include <sdktools>
#include <l4d_stocks>

#include "macros.sp"
#include "helpers.sp"
/*convar handler*/
new Handle:ppipe = INVALID_HANDLE;
new Handle:pbile = INVALID_HANDLE;
new Handle:pmolly = INVALID_HANDLE;
new Handle:pkit = INVALID_HANDLE;
new Handle:ppills = INVALID_HANDLE;
new Handle:padre = INVALID_HANDLE;
new Handle:pdefib = INVALID_HANDLE;
new Handle:pexplo = INVALID_HANDLE;
new Handle:pincend = INVALID_HANDLE;

/*effective values*/
new npipe;
new nbile;
new nmolly;
new nkit;
new npills;
new nadre;
new ndefib;
new nexplosive;
new nincendiary;

/*store the players % of achievment*/
new players_number_pipe[MAXCLIENTS];
new players_number_bile[MAXCLIENTS];
new players_number_molly[MAXCLIENTS];
new players_number_kit_defib[MAXCLIENTS];
new players_number_pills_adre[MAXCLIENTS];
new players_number_explosive[MAXCLIENTS];
new players_number_incendiary[MAXCLIENTS];

/*summary */
new bool:first_round = true;
new bool:show_summary = false;

new String:best_si_killer_name[64];
new best_si_kill_number = 0;
new best_si_kill_index;

new String:best_teamate_helper_name[64];
new best_teamate_helper_number = 0;
new best_teamate_helper_index;

public OnPluginStart()
{
	ppipe = CreateConVar("l4d2_reward_pipe", "30", "How many CI to kill for reward a pipe");
	pbile = CreateConVar("l4d2_reward_bile", "2", "How many Boomer to kill for reward bile bomb");
	pmolly = CreateConVar("l4d2_reward_molotov", "11", "How many headshot to CI to reward molotov");
	pkit = CreateConVar("l4d2_reward_kit", "7", "How many teamate to revive to reward health kit");
	ppills = CreateConVar("l4d2_reward_pills", "8", "How many SI to kill to reward pills");
	padre = CreateConVar("l4d2_reward_adrenaline", "16", "How many SI to kill to reward adrenaline");
	pdefib = CreateConVar("l4d2_reward_defibrilator", "10", "How many teamate to revive to reward defibrilator");
	pexplo = CreateConVar("l4d2_reward_explosive", "2", "How many Smoker to kill to reward explosive ammo");
	pincend = CreateConVar("l4d2_reward_incendiary", "8", "How many Charger to kill to reward incendiary ammo");

	HookConVarChange(ppipe, ConVarChanged);
	HookConVarChange(pbile, ConVarChanged);
	HookConVarChange(pmolly, ConVarChanged);
	HookConVarChange(pkit, ConVarChanged);
	HookConVarChange(ppills, ConVarChanged);
	HookConVarChange(padre, ConVarChanged);
	HookConVarChange(pdefib, ConVarChanged);
	HookConVarChange(pexplo, ConVarChanged);
	HookConVarChange(pincend, ConVarChanged);

	//Execute the config file
	AutoExecConfig(true, "l4d2_reward");
	
	read_cvar();

	/*hook event to reward */
	HookEvent("round_start", Event_RoundStart);
	HookEvent("round_end", Event_RoundEnd);
	HookEvent("infected_death", Event_InfectedDie);
	HookEvent("charger_killed", Event_ChargerKilled);
	HookEvent("boomer_exploded", Event_BoomerExplode);
	HookEvent("revive_success", Event_TeamateRevived);
	HookEvent("player_death", Event_SpecialKilled);
	HookEvent("player_disconnect", Event_PlayerDisconnect);
}


public Action:Event_PlayerDisconnect(Handle:event, const String:name[], bool:dontBroadcast)
{
	new id = GetClientOfUserId(GetEventInt(event, "userid"));
	if(IsValidClient(id))
		{
			players_number_pipe[id] = 0;
			players_number_bile[id] = 0;
			players_number_molly[id] = 0;
			players_number_kit_defib[id]= 0;
			players_number_pills_adre[id] = 0;
			players_number_incendiary[id] = 0;
			players_number_explosive[id] = 0;
		}
}

public OnMapStart()

{
	PrecacheSound(SOUND_REWARD);
}

public OnMapEnd()
{
	first_round = true;
	show_summary = false;	
}

public clear_arrays()
{
	for(new i=1;i < MAXCLIENTS;i++)
	{
		players_number_pipe[i] = 0;
		players_number_bile[i] = 0;
		players_number_molly[i] = 0;
		players_number_kit_defib[i]= 0;
		players_number_pills_adre[i] = 0;
		players_number_incendiary[i] = 0;
		players_number_explosive[i] = 0;	
	}
}

public read_cvar()
{
	nmolly =  GetConVarInt(pmolly);
	npipe =  GetConVarInt(ppipe);
	nbile = GetConVarInt(pbile);
	nkit = GetConVarInt(pkit);
	npills = GetConVarInt(ppills);
	nadre = GetConVarInt(padre);
	ndefib = GetConVarInt(pdefib);
	nexplosive = GetConVarInt(pexplo);
	nincendiary = GetConVarInt(pincend);

}
public ConVarChanged(Handle:convar, const String:oldValue[], const String:newValue[])
{
	read_cvar();
}

public Event_RoundStart(Handle:event, const String:name[], bool:dontBroadcast)
{
	clear_arrays();

	if(first_round) // 1st round
	{
		first_round = false;		
		show_summary = false;
	}
	else //2nd round
	{
		show_summary = true;
		first_round = true;
	}

}

public Event_RoundEnd(Handle:event, const String:name[], bool:dontBroadcast)
{
	if(show_summary && best_teamate_helper_number > 0)
	{
		/* display in green for winner and yellow to other*/
		if(IsValidClient(best_teamate_helper_index))
		{
			decl String:check_name[64];
			GetClientName(best_teamate_helper_index, check_name, sizeof(check_name));

			/* the winner is connected */
			if(strcmp(check_name, best_teamate_helper_name) == 0)
			{
				PrintToChat(best_teamate_helper_index, "\x01Best \x05Teamate Helper\x01 : \x05%s\x01 with \x05%d\x01 revives", best_teamate_helper_name, best_teamate_helper_number);
				PrintToChatAllExclude(best_teamate_helper_index, -1, "\x01Best \x04Teamate Helper\x01 : \x04%s\x01 with \x04%d\x01 revives", best_teamate_helper_name, best_teamate_helper_number);
			}
			else //the winner has left, print yellow for everyone
			{
				PrintToChatAll("\x01Best \x04Teamate Helper\x01 : \x04%s\x01 with \x04%d\x01 revives", best_teamate_helper_name, best_teamate_helper_number);
			}
		}
		else //should not happen, but in case, print to all in yellow if client became invalid
		{
			PrintToChatAll("\x01Best \x04Teamate Helper\x01 : \x04%s\x01 with \x04%d\x01 revives", best_teamate_helper_name, best_teamate_helper_number);
		}
		best_teamate_helper_number = 0;
		best_teamate_helper_index = 0;
		strcopy(best_teamate_helper_name, sizeof(best_teamate_helper_name), "Nobody");
	}

	if(show_summary && best_si_kill_number > 0)
	{

		/* display in green for winner and yellow to other*/
		if(IsValidClient(best_si_kill_index))
		{
			decl String:check_name[64];
			GetClientName(best_si_kill_index, check_name, sizeof(check_name));

			/* the winner is connected */
			if(strcmp(check_name, best_si_killer_name) == 0)
			{
				PrintToChat(best_si_kill_index, "\x01Best \x05SI Killer\x01 : \x05%s\x01 with \x05%d\x01 kills", best_si_killer_name, best_si_kill_number);
				PrintToChatAllExclude(best_si_kill_index, -1, "\x01Best \x04SI Killer\x01 : \x04%s\x01 with \x04%d\x01 kills", best_si_killer_name, best_si_kill_number);
			}
			else //the winner has left, print yellow for everyone
			{
				PrintToChatAll("\x01Best \x04SI Killer\x01 : \x04%s\x01 with \x04%d\x01 kills", best_si_killer_name, best_si_kill_number);
			}
		}
		else //should not happen, but in case, print to all in yellow if client became invalid
		{
			PrintToChatAll("\x01Best \x04SI Killer\x01 : \x04%s\x01 with \x04%d\x01 kills", best_si_killer_name, best_si_kill_number);
		}

		best_si_kill_number = 0;
		best_si_kill_index = 0;
		strcopy(best_si_killer_name, sizeof(best_si_killer_name), "Nobody");
	}

	show_summary = false;
}


/*********** PIPE BOMB and MOLLY *************/
public Event_InfectedDie(Handle:event, const String:name[], bool:dontBroadcast)
{
	new userid = GetClientOfUserId(GetEventInt(event, "attacker"));

	if(IsValidHumanSurvivorAlive(userid))
	{
		new bool:hs = GetEventBool(event, "headshot");

		if(hs)
		{			
			players_number_molly[userid]++;
			if(players_number_molly[userid] % nmolly == 0)
			{
				PrintToChat(userid, "\x01You won \x05molotov\x01 (%d CI headshots)", players_number_molly[userid]);
				CheatCommand(userid, "give", "molotov");
				//Play a sound to indicate he win something
				EmitSoundToClient(userid, SOUND_REWARD);

			}
			
		}
		else
		{
			players_number_pipe[userid]++;
			if(players_number_pipe[userid] % npipe == 0)
			{
				PrintToChat(userid, "\x01You won \x05pipe bomb\x01 (%d CI kills)", players_number_pipe[userid]);
				CheatCommand(userid, "give", "pipe_bomb");
				//Play a sound to indicate he win something
				EmitSoundToClient(userid, SOUND_REWARD);

			}

		}
	}
}

/*************** BILE JAR *********************/
public Event_BoomerExplode(Handle:event, const String:name[], bool:dontBroadcast)
{
	new userid = GetClientOfUserId(GetEventInt(event, "attacker"));
	if(IsValidHumanSurvivorAlive(userid))
	{
		new bool:boomed = GetEventBool(event, "splashedbile");
		if(!boomed) /* player have to not be boomed by boomer killed */
		{
			players_number_bile[userid]++;
			if(players_number_bile[userid] % nbile == 0)
			{
				PrintToChat(userid, "\x01You won \x05vomit jar\x01 (%d Boomer kills w/o blind)", players_number_bile[userid]);
				CheatCommand(userid, "give", "vomitjar");
				//Play a sound to indicate he win something
				EmitSoundToClient(userid, SOUND_REWARD);

			}

		}
	}
}


/******************** MED KIT AND DEFIB ***************************/
public Event_TeamateRevived(Handle:event, const String:name[], bool:dontBroadcast)
{
	new user_reviver = GetEventInt(event, "userid");
	new user_revived = GetEventInt(event, "subject");
	new userid = GetClientOfUserId(user_reviver);
	if(user_reviver != user_revived && IsValidHumanSurvivorAlive(userid)) /* avoid self help */
	{
		players_number_kit_defib[userid]++;
		

		if(players_number_kit_defib[userid] % ndefib == 0)
		{
			PrintToChat(userid, "\x01You won \x05defibrillator\x01 (%d teamates revives)", players_number_kit_defib[userid]);
			CheatCommand(userid, "give", "defibrillator");
			//Play a sound to indicate he win something
			EmitSoundToClient(userid, SOUND_REWARD);
		}
		else if(players_number_kit_defib[userid] % nkit == 0)
		{
			PrintToChat(userid, "\x01You won \x05health kit\x01 (%d teammates revives)", players_number_kit_defib[userid]);
			CheatCommand(userid, "give", "first_aid_kit");
			//Play a sound to indicate he win something
			EmitSoundToClient(userid, SOUND_REWARD);
		}

		/*make stats */
		if(players_number_kit_defib[userid] > best_teamate_helper_number)
		{
			best_teamate_helper_number = players_number_kit_defib[userid];
			GetClientName(userid, best_teamate_helper_name, sizeof(best_teamate_helper_name));
			best_teamate_helper_index = userid;
		}

	}
}

/********************* PILLS & ADRENALINE *****************/
public Event_SpecialKilled(Handle:event, const String:name[], bool:dontBroadcast)
{	
	new userid = GetClientOfUserId(GetEventInt(event, "attacker"));
	new deadinf = GetClientOfUserId(GetEventInt(event, "userid"));
	if (IsValidHumanSurvivorAlive(userid) && IsValidInfected(deadinf)) /* survivor kill an SI */
	{
		players_number_pills_adre[userid]++;

		if(players_number_pills_adre[userid] % nadre == 0)
		{
			PrintToChat(userid, "\x01You won \x05adrenaline\x01 (%d SI kills)", players_number_pills_adre[userid]);
			CheatCommand(userid, "give", "adrenaline");
			//Play a sound to indicate he win something
			EmitSoundToClient(userid, SOUND_REWARD);
		}
		else if(players_number_pills_adre[userid] % npills == 0)
		{
			PrintToChat(userid, "\x01You won \x05pills\x01 (%d SI kills)", players_number_pills_adre[userid]);
			CheatCommand(userid, "give", "pain_pills");
			//Play a sound to indicate he win something
			EmitSoundToClient(userid, SOUND_REWARD);
		}


		/*make stats */
		if(players_number_pills_adre[userid] > best_si_kill_number)
		{
			best_si_kill_number = players_number_pills_adre[userid];
			GetClientName(userid, best_si_killer_name, sizeof(best_si_killer_name));
			best_si_kill_index = userid;
		}


		/*****************UPGRADE AMMO ************************/
		
		new String:vicname[32];
		GetEventString(event, "victimname", vicname, sizeof(vicname));

		if(strcmp(vicname, "Smoker") == 0)
		{
			players_number_explosive[userid]++;

			if(players_number_explosive[userid] % nexplosive == 0)
			{
				PrintToChat(userid, "\x01You won \x05explosive ammo\x01 (%d Smoker kills)", players_number_explosive[userid]);
				CheatCommand(userid, "upgrade_add", "explosive_ammo");
				//Play a sound to indicate he win something
				EmitSoundToClient(userid, SOUND_REWARD);

			}
		}

		
	}

}

public Event_ChargerKilled(Handle:event, const String:name[], bool:dontBroadcast)
{

	new userid = GetClientOfUserId(GetEventInt(event, "attacker"));

	if(IsValidHumanSurvivor(userid))
	{
		players_number_incendiary[userid]++;

		if(players_number_incendiary[userid] % nincendiary == 0)
		{
			PrintToChat(userid, "\x01You won \x05incendiary ammo\x01 (%d Charger kills)", players_number_incendiary[userid]);
			CheatCommand(userid, "upgrade_add", "incendiary_ammo");
			//Play a sound to indicate he win something
			EmitSoundToClient(userid, SOUND_REWARD);

		}
	}
}
